﻿/******************************************************************************
 * This file is part of libemb.
 *
 * libemb is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * libemb is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with libemb.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Project: Embedme
 * Author : FergusZeng
 * Email  : cblock@126.com
 * git	  : https://git.oschina.net/cblock/embedme
 * Copyright 2014~2017 @ ShenZhen ,China
*******************************************************************************/
#ifndef __THREAD_H__
#define __THREAD_H__

#include "BaseType.h"
#include "Mutex.h"
#include <pthread.h>
#include <unistd.h>
#include <iostream>
#include <vector>

namespace libemb{
class ThreadPool;
/**
 *  \file   Thread.h   
 *  \class  Runnable
 *  \brief  线程体,子类必须重写run方法.	
 */
class Runnable{
public:
	Runnable();
	virtual ~Runnable();
	virtual void run()=0;
    bool isStarted();
    bool checkThreadCancel();
private:
    friend class ThreadPool;
    bool m_isStarted;
};

typedef enum{
    THREAD_STATUS_NEW=0,
    THREAD_STATUS_START,
    THREAD_STATUS_RUNNING,
    THREAD_STATUS_EXIT,
}THREAD_STATUS_E;

typedef enum{
    TASK_STATUS_STOP=0,
    TASK_STATUS_START,
    TASK_STATUS_EXIT,
}TASK_STATUS_E;

/* 请注意:任务方法原型必须是void task(void*arg),否则在任务中可能无法使用成员变量!!! */
typedef void (Runnable::*SEL_task)(void* arg);
#define task_selector(SELECTOR) (SEL_task)(&SELECTOR)

/**
 *  \file   Thread.h   
 *  \class  Thread
 *  \brief  线程类	
 */
class Thread{
public:
	Thread(int stackSize=-1);
	virtual ~Thread();
	bool start(Runnable* pRunnable);
    void join();
    bool cancel();
	bool isRunning();
    int getStatus();
    static void msleep(int ms);
    static int createTask(Runnable* owner,SEL_task task,void* taskArg);
private:
    void threadMain();
    static void* threadEntry(void *arg);
    static void* taskEntry(void *arg);
private:
	Runnable* m_pRunnableTarget;
	pthread_t m_threadID;
	pthread_attr_t m_ThreadAttr;
	THREAD_STATUS_E m_threadStatus;
    int m_threadStackSize;
};

/**
 *  \file   Thread.h   
 *  \class  ThreadPool
 *  \brief  线程池
 */
class ThreadPool{
public:
    static ThreadPool* getInstance()
    {
        static ThreadPool instance;
        return &instance;
    }
    ~ThreadPool();
    bool init(int maxThreadCount);
    bool start(Runnable* runnable,int priority=0);
    bool cancel(Runnable* runnable);
    int maxThreadCount();
    int idleThreadCount();
private:
    ThreadPool();
    void startThread(int index);
    static void* threadEntry(void *arg);
private:
    bool m_initFlag;
    MutexLock m_vectLock;
    std::vector<Runnable*> m_threadVect;
    int m_maxThreadCount;
    int m_usedThreadCount;
};
}
#endif
